00001
00002
00003
00004
00005
00006
00007 #include "ext.h"
00008 #include "ext_obex.h"
00009 #include "ext_time.h"
00010 #include "ext_itm.h"
00011
00012
00013 typedef struct _statelem
00014 {
00015 bool enable;
00016 long pitch;
00017 double nbOcc;
00018 double nbtot;
00019 double ampacc;
00020 double proba;
00021 void* clock;
00022 void* object;
00023 } bc_statelem;
00024
00025
00027 typedef struct _bc_yinstats
00028 {
00029 t_object ob;
00030 long nbstats;
00031 bc_statelem* stats;
00032 double minproba;
00033 long window;
00034 double lastpitch;
00035 double lastamp;
00036 long laststat;
00037 void* out_pitch;
00038 void* out_amp;
00039 void* out_proba;
00040 } t_bc_yinstats;
00041
00043
00045
00046
00047 void *bc_yinstats_new(t_symbol *s, long argc, t_atom *argv);
00048 void bc_yinstats_free(t_bc_yinstats *x);
00049 void bc_yinstats_assist(t_bc_yinstats *x, void *b, long m, long a, char *s);
00050
00051
00052 void bc_yinstats_amp(t_bc_yinstats *x, double ampin);
00053 void bc_yinstats_pitch(t_bc_yinstats *x, long pitchin);
00054 void bc_yinstats_out(bc_statelem *stat);
00055 void bc_yinstats_stop(t_bc_yinstats *x);
00056
00057
00058 bool bc_yinstats_addocc(t_bc_yinstats *x, long pitchin, double ampin);
00059 long bc_yinstats_addstat(t_bc_yinstats *x, long pitchin, double ampin);
00060 void bc_yinstats_reset(t_bc_yinstats *x, bc_statelem *stat);
00061
00062
00063 void *bc_yinstats_class;
00064
00065
00066 int main(void)
00067 {
00068 t_class *c;
00069
00070 c = class_new("bc.yinstats", (method)bc_yinstats_new, (method)bc_yinstats_free, (long)sizeof(t_bc_yinstats), 0L, A_GIMME, 0);
00071
00072
00073 class_addmethod(c, (method)bc_yinstats_assist,"assist",A_CANT, 0);
00074
00075
00076 class_addmethod(c, (method)bc_yinstats_pitch, "int", A_LONG, 0);
00077 class_addmethod(c, (method)bc_yinstats_amp, "ft1", A_FLOAT, 0);
00078 class_addmethod(c, (method)bc_yinstats_stop, "stop", 0);
00079
00080 CLASS_ATTR_LONG(c, "window", 0, t_bc_yinstats, window);
00081 CLASS_ATTR_LABEL(c, "window", 0, "Window (ms)");
00082 CLASS_ATTR_SAVE(c, "window", 0);
00083 CLASS_ATTR_MIN(c, "window", 0, 0);
00084
00085 CLASS_ATTR_DOUBLE(c, "minproba", 0, t_bc_yinstats, minproba);
00086 CLASS_ATTR_LABEL(c, "minproba", 0, "Probability Threshold");
00087 CLASS_ATTR_SAVE(c, "minproba", 0);
00088 CLASS_ATTR_FILTER_CLIP(c, "minproba", 0., 1.);
00089
00090 class_register(CLASS_BOX, c);
00091 bc_yinstats_class = c;
00092
00093 return 0;
00094 }
00095
00096
00097 void *bc_yinstats_new(t_symbol *s, long argc, t_atom *argv)
00098 {
00099 t_bc_yinstats *x = NULL;
00100
00101
00102 if (x = (t_bc_yinstats *)object_alloc(bc_yinstats_class))
00103 {
00104
00105 floatin(x, 1);
00106
00107
00108 x->out_proba = floatout(x);
00109 x->out_amp = floatout(x);
00110 x->out_pitch = intout(x);
00111
00112 x->nbstats = 100;
00113 x->minproba = 0.;
00114
00115
00116 switch (argc)
00117 {
00118
00119
00120
00121
00122
00123
00124
00125
00126 case 1:
00127 if (argv->a_type == A_LONG)
00128 x->nbstats = atom_getlong(argv);
00129 break;
00130 default:
00131 object_error((t_object *)x, "Number of stat agents needed");
00132 }
00133
00134
00135
00136 attr_args_process(x, argc, argv);
00137
00138 x->stats = (bc_statelem*)sysmem_newptr(x->nbstats * sizeof(bc_statelem));
00139 long i;
00140 for (i = 0; i< x->nbstats; i++)
00141 bc_yinstats_reset(x, x->stats + i);
00142 x->laststat = 0;
00143 }
00144 return (x);
00145 }
00146
00147
00148 void bc_yinstats_free(t_bc_yinstats *x)
00149 {
00150 long i;
00151 for (i = 0; i< x->nbstats; i++)
00152 {
00153 freeobject(x->stats[i].clock);
00154 }
00155 sysmem_freeptr(x->stats);
00156 }
00157
00158
00159 void bc_yinstats_assist(t_bc_yinstats *x, void *b, long io, long index, char *s)
00160 {
00161 switch (io)
00162 {
00163 case 1:
00164 switch (index)
00165 {
00166 case 0:
00167 sprintf(s, "pitch");
00168 break;
00169 case 1:
00170 sprintf(s, "amplitude");
00171 break;
00172 }
00173 break;
00174 case 2:
00175 switch (index)
00176 {
00177 case 0:
00178 sprintf(s, "coocked pitch");
00179 break;
00180 case 1:
00181 sprintf(s, "average amplitude");
00182 break;
00183 case 2:
00184 sprintf(s,"probability");
00185 break;
00186 }
00187 }
00188 }
00189
00190 void bc_yinstats_amp(t_bc_yinstats *x, double ampin)
00191 {
00192 x->lastamp = ampin;
00193 }
00194
00195 void bc_yinstats_pitch(t_bc_yinstats *x, long pitchin)
00196 {
00197 x->lastpitch = pitchin;
00198 bc_yinstats_addocc(x, pitchin, x->lastamp);
00199 bc_yinstats_addstat(x, pitchin, x->lastamp);
00200 }
00201
00202 bool bc_yinstats_addocc(t_bc_yinstats *x, long pitchin, double ampin)
00203 {
00204 long i;
00205 bool found = FALSE;
00206 for (i = 0; i<=(x->laststat); i++)
00207 {
00208 if (x->stats[i].enable)
00209 {
00210 x->stats[i].nbtot++;
00211 if (x->stats[i].pitch == pitchin)
00212 {
00213 found = TRUE;
00214 x->stats[i].nbOcc++;
00215 x->stats[i].ampacc += ampin;
00216 }
00217 }
00218 }
00219 return found;
00220 }
00221
00222 long bc_yinstats_addstat(t_bc_yinstats *x, long pitchin, double ampin)
00223 {
00224 long i = 0;
00225 while (x->stats[i].enable && i<x->nbstats)
00226 i++;
00227 if (i == x->nbstats)
00228 {
00229 i = 0;
00230 object_error((t_object *)x, "too many events");
00231 }
00232 x->stats[i].enable = TRUE;
00233 x->stats[i].pitch = pitchin;
00234 x->stats[i].ampacc = ampin;
00235 x->stats[i].nbOcc = 1;
00236 x->stats[i].nbtot = 1;
00237 clock_delay(x->stats[i].clock, x->window);
00238 if (i > (x->laststat))
00239 x->laststat = i;
00240 return i;
00241 }
00242
00243 void bc_yinstats_reset(t_bc_yinstats *x, bc_statelem *stat)
00244 {
00245 stat->enable = FALSE;
00246 stat->pitch = 0;
00247 stat->ampacc = 0.;
00248 stat->nbOcc = 0;
00249 stat->nbtot = 0;
00250 stat->proba = 0.;
00251 stat->object = x;
00252 stat->clock = clock_new(stat , (method)bc_yinstats_out);
00253 }
00254
00255 void bc_yinstats_out(bc_statelem *stat)
00256 {
00257 t_bc_yinstats * x = stat->object;
00258 stat->proba = stat->nbOcc / stat->nbtot;
00259 if (stat->proba >= x->minproba)
00260 {
00261 outlet_float(x->out_proba, stat->proba);
00262 outlet_float(x->out_amp, stat->ampacc / stat->nbOcc);
00263 outlet_int(x->out_pitch, stat->pitch);
00264 }
00265 stat->enable = FALSE;
00266 }
00267
00268 void bc_yinstats_stop(t_bc_yinstats *x)
00269 {
00270 long i;
00271 for (i = 0; i< x->laststat; i++)
00272 {
00273 x->stats[i].enable = FALSE;
00274 clock_unset(x->stats[i].clock);
00275 }
00276 x->laststat = 0;
00277 }